import Image from '@tiptap/extension-image'

export const ResizableImage = Image.extend({
	name: 'resizableImage',

	addOptions() {
		return {
			...this.parent?.(),
			HTMLAttributes: {
				class: 'resizable-image'
			}
		}
	},

	addAttributes() {
		return {
			...this.parent?.(),
			width: {
				default: '100%',
				parseHTML: element => element.style.width || '100%',
				renderHTML: attributes => ({ style: `width: ${attributes.width}` })
			},
			height: {
				default: 'auto',
				parseHTML: element => element.style.height || 'auto',
				renderHTML: attributes => ({ style: `height: ${attributes.height}` })
			}
		}
	},

	addNodeView() {
		return ({ node, HTMLAttributes, getPos, editor }) => {
			const wrapper = document.createElement('div')
			wrapper.className = 'resizable-image-wrapper'

			const image = document.createElement('img')
			image.src = node.attrs.src
			image.className = HTMLAttributes.class
			image.style.width = node.attrs.width
			image.style.height = node.attrs.height

			const handle = document.createElement('div')
			handle.className = 'resize-handle'

			wrapper.append(image, handle)

			let isResizing = false
			let startX, startY, startWidth, startHeight

			const onMouseDown = e => {
				e.preventDefault()
				isResizing = true
				startX = e.clientX
				startY = e.clientY
				startWidth = parseInt(image.style.width)
				startHeight = parseInt(image.style.height)

				document.addEventListener('mousemove', onMouseMove)
				document.addEventListener('mouseup', onMouseUp)
			}

			const onMouseMove = e => {
				if (!isResizing) {
					return
				}

				const dx = e.clientX - startX
				const dy = e.clientY - startY

				const newWidth = startWidth + dx
				const newHeight = startHeight + dy

				image.style.width = `${newWidth}px`
				image.style.height = `${newHeight}px`
			}

			const onMouseUp = () => {
				isResizing = false
				const transaction = editor.state.tr.setNodeMarkup(getPos(), undefined, {
					...node.attrs,
					width: image.style.width,
					height: image.style.height
				})
				editor.view.dispatch(transaction)

				document.removeEventListener('mousemove', onMouseMove)
				document.removeEventListener('mouseup', onMouseUp)
			}

			handle.addEventListener('mousedown', onMouseDown)

			return {
				dom: wrapper,
				update: updatedNode => {
					if (updatedNode.type !== this.type) {
						return false
					}
					image.src = updatedNode.attrs.src
					image.style.width = updatedNode.attrs.width
					image.style.height = updatedNode.attrs.height
					return true
				}
			}
		}
	}
})
